﻿using System;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Navigation;

using ProjectEuler.Linq;

namespace ProjectEuler.UI
{
    internal sealed partial class MainWindow
    {
        static MainWindow()
        {
            EventManager.RegisterClassHandler(
                typeof(MainWindow), 
                Hyperlink.RequestNavigateEvent, 
                new RequestNavigateEventHandler(OnNavigationRequested));
        }

        public MainWindow()
        {
            InitializeComponent();
        }

        private ProblemInfoCollection Problems
        {
            get { return (ProblemInfoCollection)Resources["Problems"]; }
        }

        private ProblemRun Session
        {
            get { return (ProblemRun)Resources["Session"]; }
        }

        protected override void OnKeyUp(KeyEventArgs e)
        {
            base.OnKeyUp(e);

            if (e.Key == Key.Escape)
            {
                if (Commands.Cancel.CanExecute(null, this))
                {
                    Commands.Cancel.Execute(null, this);
                }

                if (ApplicationCommands.Close.CanExecute(null, this))
                {
                    ApplicationCommands.Close.Execute(null, this);
                }
            }
        }

        private void OnCancelExecuted(Object sender, ExecutedRoutedEventArgs e)
        {
            Session.Stop();
        }

        private void OnCopyAnswerExecuted(Object sender, ExecutedRoutedEventArgs e)
        {
            var problem = (e.Parameter as ProblemInfo);

            if ((problem != null) && (problem.Answer != null))
            {
                Clipboard.SetText(problem.Answer.ToString());
            }
        }

        private void OnCloseExecuted(Object sender, ExecutedRoutedEventArgs e)
        {
            Close();
        }

        private void OnRunExecuted(Object sender, ExecutedRoutedEventArgs e)
        {
            Problems.ForEach(p => p.ResetResult());
            Session.Start(Problems.Where(p => p.IsSelected));
        }

        private void OnCanExecuteCancel(Object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = (Session.CurrentStatus == ProblemRunStatus.Executing);
        }

        private void OnCanExecuteCopyAnswer(Object sender, CanExecuteRoutedEventArgs e)
        {
            var problem = (e.Parameter as ProblemInfo);

            if (problem != null)
            {
                e.CanExecute = (problem != null) && (problem.Answer != null);
            }
        }

        private void OnCanExecuteClose(Object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = (Session.CurrentStatus == ProblemRunStatus.None);
        }

        private void OnCanExecuteRun(Object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = (Session.CurrentStatus == ProblemRunStatus.None) && Problems.Any(p => p.IsSelected);
        }

        private void OnSessionCompleted(Object sender, EventArgs e)
        {
            CommandManager.InvalidateRequerySuggested();
        }

        private static void OnNavigationRequested(Object sender, RequestNavigateEventArgs e)
        {
            ShellExecute(e.Uri.ToString());
        }

        private static void ShellExecute(String command)
        {
            var psi = new ProcessStartInfo()
            {
                UseShellExecute = true,
                FileName = command,
            };

            using (Process.Start(psi))
            {
            }
        }
    }
}